<!DOCTYPE html>
<html>

<head>
    <title>Layui虚拟化方案</title>
    <link rel="stylesheet" href="https://www.layuicdn.com/layui/css/layui.css">
    <style>
        .select-container {
            margin: 20px;
            display: flex;
            align-items: center;
            gap: 20px;
        }

        .ball-container {
            width: 200px;
            height: 60px;
            border: 1px solid #ccc;
            position: relative;
        }

        .ball {
            width: 20px;
            height: 20px;
            background-color: red;
            border-radius: 50%;
            position: absolute;
            animation: moveBall 4s linear infinite;
        }

        @keyframes moveBall {
            0% {
                left: 0;
                top: 0;
            }

            25% {
                left: calc(100% - 20px);
                top: 0;
            }

            50% {
                left: calc(100% - 20px);
                top: calc(100% - 20px);
            }

            75% {
                left: 0;
                top: calc(100% - 20px);
            }

            100% {
                left: 0;
                top: 0;
            }
        }
    </style>
</head>

<body class="layui-form">
    <div class="select-container">
        <label>省份选择：</label>
        <div class="layui-inline">
            <div class="layui-input-inline" style="width: 300px;">
                <select name="province" id="provinceSelect" lay-filter="province" lay-search lay-creatable
                    lay-verify="required">
                    <!-- <option value="">请选择省份</option> -->
                </select>
            </div>
        </div>
        <div class="ball-container">
            <div class="ball"></div>
        </div>
    </div>

    <div class="select-container">
        <label>城市选择：</label>
        <div class="layui-inline">
            <div class="layui-input-inline" style="width: 300px;">
                <select name="city" id="citySelect" lay-filter="city" lay-search lay-verify="required">
                    <!-- <option value="">请选择城市</option> -->
                </select>
            </div>
        </div>
    </div>

    <div class="select-container">
        <label>区域选择：</label>
        <div class="layui-inline">
            <div class="layui-input-inline" style="width: 300px;">
                <select name="area" id="areaSelect" lay-filter="area" lay-search lay-verify="required">
                    <!-- <option value="">请选择区域</option> -->
                </select>
            </div>
        </div>
    </div>

    <script src="https://www.layuicdn.com/layui/layui.js"></script>
    <script>
        layui.use(['form', 'layer'], function () {
            var form = layui.form;
            var layer = layui.layer;
            var $ = layui.$;
            // 创建防抖函数
            function debounce(fn, delay) {
                let timer = null;
                return function (...args) {
                    if (timer) clearTimeout(timer);
                    timer = setTimeout(() => {
                        fn.apply(this, args);
                    }, delay);
                };
            }

            const dataMap = new Map();
            const searchTextMap = new Map();
            // 生成测试数据
            function generateMockData(prefix, count) {
                return Array.from({ length: count }, (_, i) => ({
                    value: i,
                    text: `${prefix}-${i}`
                }));
            }

            const selectName = {
                'provinceSelect': '省份',
                'citySelect': '城市',
                'areaSelect': '区域'
            };
            // 初始化数据
            const provinceData = generateMockData('省份', 5000);
            const cityData = generateMockData('城市', 8000);
            const areaData = generateMockData('区域', 10000);
            // 将数据存储到 Map 中
            dataMap.set('provinceSelect', provinceData);
            dataMap.set('citySelect', cityData);
            dataMap.set('areaSelect', areaData);
            // 虚拟滚动加载选项
            function loadVirtualOptions(selectId, data,form) {
                const select = document.getElementById(selectId);
                const itemHeight = 42;
                const visibleItems = 10;
                const bufferItems = 5;
                let startIndex = 0;
                // 添加"请选择"选项 - 修复选项文本
                const select_name = selectName[select.id] ?? select.name;
                // 初始化 select 元素的所有选项
                function initializeSelectOptions() {
                    const fragment = document.createDocumentFragment();
                    const defaultOption = select.querySelector('option[value=""]');
                    select.innerHTML = '';
                    select.appendChild(defaultOption ?? new Option(`请选择${select_name}`, ''));

                    data.forEach(item => {
                        const option = document.createElement('option');
                        option.value = item.value;
                        option.text = item.text;
                        fragment.appendChild(option);
                    });

                    select.appendChild(fragment);
                    // form.render('select');
                }

                // 更新可见选项
                function updateVisibleOptions(scrollTop) {
                    const $select = $(select).next('.layui-form-select');
                    const $dl = $select.find('dl.layui-anim');

                    // 设置下拉框样式
                    $dl.css({
                        'max-height': '300px',
                        'overflow-y': 'auto'
                    });

                    // 计算显示范围
                    startIndex = Math.floor(scrollTop / itemHeight);
                    const start = Math.max(0, startIndex);
                    const end = Math.min(data.length, startIndex + visibleItems + bufferItems);

                    // 清空现有选项
                    $dl.empty();

                    // 添加顶部填充
                    if (start > 0) {
                        $dl.append($('<div>').css({
                            height: start * itemHeight + 'px',
                            padding: 0,
                            margin: 0
                        }));
                    }
                    $dl.append($('<dd lay-value="">请选择' + select_name + '</dd>'));
                    if (data.length === 0) {
                        $dl.append($('<dd lay-value="">' + searchTextMap.get(selectId) + '</dd>'));
                    }
                    // 添加数据选项
                    for (let i = start; i < end; i++) {
                        const $dd = $('<dd></dd>')
                            .attr('lay-value', data[i].value)
                            .text(data[i].text);

                        if (data[i].value === select.value) {
                            $dd.addClass('layui-this');
                        }

                        $dl.append($dd);
                    }

                    // 添加底部填充
                    if (end < data.length) {
                        $dl.append($('<div>').css({
                            height: (data.length - end) * itemHeight + 'px',
                            padding: 0,
                            margin: 0
                        }));
                    }

                    // 设置总高度
                    const totalHeight = (data.length + 1) * itemHeight;
                    $dl.height(totalHeight);
                }
                //获取过滤后的数据
                function getFilterData(searchText) {
                    if (!searchText) {
                        return dataMap.get(selectId) || [];
                    }
                    const searchValue = searchText.toLowerCase();
                    return (dataMap.get(selectId) || []).filter(item =>
                        item.text.toLowerCase().includes(searchValue) ||
                        String(item.value).toLowerCase().includes(searchValue)
                    );
                }

                // 处理滚动事件
                function eventhandle() {
                    const $select = $(select).next('.layui-form-select');
                    const $dl = $select.find('dl.layui-anim');

                    // 监听下拉框展开事件
                    $select.off('click').on('click', '.layui-select-title', function () {
                        requestAnimationFrame(() => {
                            const $dl = $select.find('dl.layui-anim');
                            const $input = $select.find('input');
                            // 设置输入框的值和占位符
                            $input.val(searchTextMap.get(selectId) || '');
                            $input.attr('placeholder', `请选择${select_name}`);

                            $dl.css({
                                'max-height': '300px',
                                'overflow-y': 'auto'
                            });
                            updateVisibleOptions(0);
                        });
                    });
                    // 处理搜索输入的函数
                    const handleSearch = debounce(function (e) {
                        requestAnimationFrame(() => {

                            const searchValue = $(this).val().toLowerCase();
                            // // 过滤数据
                            // const filteredData = dataMap.get(selectId).filter(item =>
                            //     item.text.toLowerCase().includes(searchValue) ||
                            //     String(item.value).toLowerCase().includes(searchValue)
                            // );

                            // 更新选项显示和数据
                            loadVirtualOptions(selectId, getFilterData(searchValue));
                            searchTextMap.set(selectId, searchValue);

                            // 手动触发下拉框展开事件
                            const $select = $(select).next('.layui-form-select');
                            $select.find('.layui-select-title').trigger('click');

                            const $input = $select.find('input');
                            // 设置输入框的值和占位符
                            $input.val(searchTextMap.get(selectId) || '');
                            $input.trigger('focus');// 触发输入框获取焦点事件
                        });

                    }, 500);

                    // 监听搜索键盘up输入事件
                    $select.off('keyup').on('keyup', 'input', handleSearch);
                    // 使用 requestAnimationFrame 优化滚动事件
                    let ticking = false;
                    $dl.off('scroll').on('scroll', function () {
                        if (!ticking) {
                            requestAnimationFrame(() => {
                                updateVisibleOptions($(this).scrollTop());
                                ticking = false;
                            });
                            ticking = true;
                        }
                    });
                }

                // 初始化顺序调整
                initializeSelectOptions();
                form.render('select'); // 确保 select 渲染完成
                setTimeout(() => {
                    eventhandle();
                    updateVisibleOptions(0);
                }, 0);
            }



            // 加载数据
            for (const [selectId, data] of dataMap) {
                loadVirtualOptions(selectId, data,form);
            }

            // 监听选择事件
            form.on('select(province)', function (data) {
                if (data.value) {
                    layer.msg('选择的省份：' + data.value);
                }
            });

            form.on('select(city)', function (data) {
                if (data.value) {
                    layer.msg('选择的城市：' + data.value);
                }
            });

            form.on('select(area)', function (data) {
                if (data.value) {
                    layer.msg('选择的区域：' + data.value);
                }
            });
        });
    </script>
    <script src="performance-monitor.js"></script>
    <script>
        const monitor = new PerformanceMonitor({
            warningThreshold: 30,
            showPanel: true,
            historySize: 10,
            updateInterval: 500,
            solutionName: 'Layui虚拟化方案',
            onFPSUpdate: ({ fps, avgFps }) => {
                if (fps < 30) {
                    console.warn(`[Layui虚拟化方案][${new Date().toLocaleTimeString()}] 性能警告: FPS=${fps}`);
                }
            }
        });

        document.addEventListener('DOMContentLoaded', () => {
            monitor.start();
        });
    </script>
</body>

</html>